package com.scalar.chiptrack.adaptor.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 * User: sujan
 * Date: Dec 12, 2008
 * Time: 3:59:46 PM
 */
public class ParserResultCSVImpl implements ParserResult
{
    private Object[][] data;
    private LinkedList headings;
    private LinkedList upperCaseHeadings;
    private boolean headingsCaseSensitive = false;

    private int currRowIdx = -1;
    private int dataStartLineIdx = 0;
    public boolean next()
    {
        if ( data != null && (currRowIdx +1) < data.length )
        {
            currRowIdx = currRowIdx +1;
        }
        else
        {
            return false;
        }
        return true;
    }
    public void reset()
    {
        currRowIdx = -1;
    }
    public Object[][] getData() {
        return data;
    }

    public void setData(Object[][] data) {
        this.data = data;
    }

    public LinkedList getHeadings() {
        return headings;
    }

    public void setHeadings(LinkedList headings) {
        this.headings = headings;
        if ( headings != null )
        {
            upperCaseHeadings = new LinkedList();
            for(int i= 0; i < headings.size(); i++ )
            {
                upperCaseHeadings.add( headings.get(i) != null ? ((String)headings.get(i)).toUpperCase() : null );
            }
        }
    }

    public LinkedList getUpperCaseHeadings() {
        return upperCaseHeadings;
    }

    public void setUpperCaseHeadings(LinkedList upperCaseHeadings) {
        this.upperCaseHeadings = upperCaseHeadings;
    }

    public String getString ( String colName )
    {
        checkCurrentState();
        int colIdx = getIndexOf(colName);
        if ( colIdx < 0 )
        {
            throw new RuntimeException( "Column '" + colName + "' Not Found" );
        }
        return getString ( colIdx );
    }
    public String getString( int colIdx )
    {
        checkCurrentState();
        String value = (String)data[currRowIdx][colIdx];
        return value == null || value.trim().length() == 0 ? null : value.trim();
    }
    public int getInt ( String colName )
    {
        checkCurrentState();
        int colIdx = getIndexOf(colName);
        if ( colIdx < 0 )
        {
            throw new RuntimeException( "Column '" + colName + "' Not Found" );
        }
        return getInt ( colIdx );
    }
    public int getInt ( int colIdx )
    {
        checkCurrentState();
        String strValue = (String)data[currRowIdx][colIdx];
        int value = 0;
        String allowedChars = "0123456789.";
        if ( strValue != null && strValue.trim().length() > 0 )
        {
            StringBuffer filtered = new StringBuffer();
            for ( int i=0; i < strValue.length(); i++ )
            {
                char c = strValue.charAt(i);
                if ( allowedChars.indexOf(c) >= 0 )
                {
                    filtered.append(c);
                }
            }

            if (filtered.toString() != null && filtered.toString().length() > 0 )
            {
                value = (int)Double.parseDouble( filtered.toString() );
            }    
        }
        return value;
    }
    public double getDouble ( String colName )
    {
        checkCurrentState();
        int colIdx = getIndexOf(colName);
        if ( colIdx < 0 )
        {
            throw new RuntimeException( "Column '" + colName + "' Not Found" );
        }

        return getDouble ( colIdx );
    }
    public double getDouble ( int colIdx )
    {
        checkCurrentState();
        String strValue = (String)data[currRowIdx][colIdx];
        double value = 0;
        String allowedChars = "0123456789.";
        if ( strValue != null && strValue.trim().length() > 0 )
        {
            StringBuffer filtered = new StringBuffer();
            for ( int i=0; i < strValue.length(); i++ )
            {
                char c = strValue.charAt(i);
                if ( allowedChars.indexOf(c) >= 0 )
                {
                    filtered.append(c);
                }
            }
            if (filtered.toString() != null && filtered.toString().length() > 0 )
            {
                value = Double.parseDouble( filtered.toString() );
            }   
        }
        return value;
    }
    public Date getDate ( String colName )
    {
        checkCurrentState();
        int colIdx = getIndexOf(colName);
        if ( colIdx < 0 )
        {
            throw new RuntimeException( "Column '" + colName + "' Not Found" );
        }
        return getDate ( colIdx );
    }
    public Date getDate ( int colIdx )
    {
        checkCurrentState();
        Date value = null;
        String[] datePatterns = {"MM/dd/yyyy HH:mm", "dd-MMM-yy", "MM/dd/yyyy", "MM-dd-yyyy", "MMddyyHHmmss", "MM-dd-yyyy-HH-mm-ss-SSS","yyyy/MM/dd"};
        for ( int i=0; i < datePatterns.length; i++ )
        {
            value = getDate( colIdx, datePatterns[i] );

            if ( value != null)
                break;
        }

        return value;
    }

    public Date getDate(int colIdx, String inputFormat)
    {
        checkCurrentState();
        String strValue = (String)data[currRowIdx][colIdx];
        
        Date value = null;
        if ( strValue != null && strValue.trim().length() > 0)
        {
            SimpleDateFormat sdf = new SimpleDateFormat(inputFormat);
            try
            {
                value = sdf.parse(strValue);
            }
            catch ( ParseException e ) { }
        }
        return value;
    }

    public Date getDate(String colName, String inputFormat)
    {
        checkCurrentState();
        int colIdx = getIndexOf(colName);
        if ( colIdx < 0 )
        {
            throw new RuntimeException( "Column '" + colName + "' Not Found" );
        }
        return getDate ( colIdx, inputFormat );
    }

    public String getContents ( String colName )
    {
        checkCurrentState();
        int colIdx = getIndexOf(colName);
        if ( colIdx < 0 )
        {
            throw new RuntimeException( "Column '" + colName + "' Not Found" );
        }
        return getContents ( colIdx );
    }
    public String getContents( int colIdx )
    {
        checkCurrentState();
        return (String)data[currRowIdx][colIdx];
    }

    public Object getObject(String colName)
    {
        checkCurrentState();
        int colIdx = getIndexOf(colName);
        if ( colIdx < 0 )
        {
            throw new RuntimeException( "Column '" + colName + "' Not Found" );
        }
        return getObject ( colIdx );
    }


    public Object getObject(int colIdx)
    {
        checkCurrentState();

        return data[currRowIdx][colIdx];
    }

    public void checkCurrentState()
    {
        if ( currRowIdx == -1 )
            throw new RuntimeException ( "Result Cursor is at start location, Please use next() to move to the first record" );
        if ( currRowIdx >= data.length )
            throw new RuntimeException ( "Result Cursor is at End location, use reset() to start from the initial" );
    }

    public int getRowCount()
    {
        return data==null ? 0 : data.length;
    }

    public int getFileRowIdx()
    {
        checkCurrentState();
        return currRowIdx + dataStartLineIdx;
    }

    public int getIndexOf(String headingName)
    {
        headingName = headingName.trim();
        int idx = -1;
        if ( headings != null )
        {
            if ( headingsCaseSensitive )
            {
                idx = headings.indexOf(headingName);
            }
            else
            {
                idx = upperCaseHeadings.indexOf( headingName != null ? headingName.toUpperCase() : null);
                /*for ( int i=0; i< headings.size(); i++ )
                {
                    String value = headings.get(i).toString();
                    if ( headingName == null )
                    {
                        if ( value == null )
                        {
                            idx = i;
                            break;
                        }
                    }
                    else
                    {
                        if ( headingName.equalsIgnoreCase( value ) )
                        {
                            idx = i;
                            break;
                        }
                    }
                }*/
            }
        }
        return idx;
    }

    public List checkRequiredFieldsAvailable(List requiredHeadings)
    {
        List headingsNotPresent = new ArrayList();
        if ( requiredHeadings != null && headings != null )
        {
            for ( int i=0; i < requiredHeadings.size(); i++ )
            {
                if ( headingsCaseSensitive )
                {
                    if ( !headings.contains( requiredHeadings.get(i) ) )
                    {
                        headingsNotPresent.add ( requiredHeadings.get(i) );
                    }
                }
                else
                {
                    String required = requiredHeadings.get(i).toString();
                    boolean contains = false;
                    for ( int j=0; j < headings.size(); j++ )
                    {
                        String heading = headings.get(j).toString();
                        if ( required == null )
                        {
                            if ( heading == null )
                            {
                                contains = true;
                                break;
                            }
                        }
                        else if ( required.equalsIgnoreCase( heading ) )
                        {
                            contains = true;
                            break;
                        }
                    }
                    if ( !contains )
                    {
                        headingsNotPresent.add ( requiredHeadings.get(i) );
                    }
                }
            }
        }
        return headingsNotPresent.isEmpty() ? null :headingsNotPresent;
    }

    public void moveTo(int rowIdx)
    {
        int cuurentRowIdx = currRowIdx;
        currRowIdx = rowIdx;
        try
        {
            checkCurrentState();
        }
        catch( RuntimeException re )
        {
            currRowIdx = cuurentRowIdx;
            throw re;
        }
    }

    public int getColumnCount()
    {
        return (data==null || data[0] == null ) ? 0 : data[0].length;
    }
    public void setDataStartLineIdx(int dataStartLineIdx)
    {
        this.dataStartLineIdx = dataStartLineIdx;
    }

    public boolean isHeadingsCaseSensitive() {
        return headingsCaseSensitive;
    }

    public void setHeadingsCaseSensitive(boolean headingsCaseSensitive) {
        this.headingsCaseSensitive = headingsCaseSensitive;
    }
}
